use std::sync::Arc;
use log::debug;
use rbatis::{Error, RBatis};
use rbatis::rbdc::DateTime;
use rbatis::rbdc::db::ExecResult;
use serde::{Deserialize, Serialize};

#[derive(Clone, Debug, Serialize, Deserialize)]
pub struct Vocabulary {
    pub word: String,
    pub last_recall_time: DateTime,
    pub proficiency: i32,
    pub next_recall_time: Option<DateTime>,
}

impl Vocabulary {
    pub fn from_string(word: String) -> Self {
        Vocabulary {
            word,
            last_recall_time: DateTime::now(),
            proficiency: 0,
            next_recall_time: None,
        }
    }
}

rbatis::crud!(Vocabulary{});


pub async fn add_word(rb: RBatis, word: String) -> Result<(), String> {
    let vocabulary = Vocabulary::from_string(word);
    let ret = Vocabulary::insert(&rb, &vocabulary).await;
    match ret {
        Ok(exec) => {
            debug!("{}",exec);
            Ok(())
        }
        Err(err) => { match err { Error::E(err) => { Err(err) } } }
    }
}

#[cfg(test)]
mod db_test {
    use rbatis::RBatis;
    use rbatis::rbdc::DateTime;
    use rbdc_sqlite::SqliteDriver;
    use crate::basic::Vocabulary;

    #[tokio::test]
    async fn curd_test() {
        let rb = RBatis::new();
        rb.link(SqliteDriver {}, "sqlite://./db/word.db").await.expect("Connect to server error");
        let mut word = Vocabulary {
            word: "vocabulary".to_string(),
            last_recall_time: DateTime::now(),
            proficiency: 0,
            next_recall_time: None,
        };
        let ret = Vocabulary::insert(&rb, &word).await.unwrap();
        dbg!(ret);
        word.proficiency += 1;
        let ret = Vocabulary::update_by_column(&rb, &word, "proficiency").await.unwrap();
        // dbg!(ret);
        // let ret = Vocabulary::delete_by_column(&rb, "word", "vocabulary").await.unwrap();
    }
}